package cn.algorithmdemo.sort;

import java.util.Arrays;

public class Demo04 {
    /*
        4. 快速排序
            快速排序是由东尼·霍尔所发展的一种排序算法。
            快速排序又是一种分而治之思想在排序算法上的典型应用。
            快速排序的名字起的是简单粗暴，因为一听到这个名字你就知道它存在的意义，就是快，而且效率高！
            它是处理大数据最快的排序算法之一了。

        4.1 算法步骤
        从数列中挑出一个元素，一般都是左边第一个数字，称为 “基准数”;
        创建两个指针，一个从前往后走，一个从后往前走。
        先执行后面的指针，找出第一个比基准数小的数字
        再执行前面的指针，找出第一个比基准数大的数字
        交换两个指针指向的数字
        直到两个指针相遇
        将基准数跟指针指向位置的数字交换位置，称之为：基准数归位。
        第一轮结束之后，基准数左边的数字都是比基准数小的，基准数右边的数字都是比基准数大的。
        把基准数左边看做一个序列，把基准数右边看做一个序列，按照刚刚的规则递归排序
    * */
    public static void main(String[] args) {
        /*
           快速排序：
               第一轮：以0索引的数字为基准数，确定基准数在数组中正确的位置。
               比基准数小的全部在左边，比基准数大的全部在右边。
               后面以此类推。
        */
        int[] arr = {1,1, 6, 2, 7, 9, 3, 4, 5, 1,10, 8};
        System.out.println(Arrays.toString(arr));
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }

    /*
     *   参数一：我们要排序的数组
     *   参数二：要排序数组的起始索引
     *   参数三：要排序数组的结束索引
     * */
    private static void quickSort(int[] arr, int i, int j) {
        //定义两个变量记录要查找的范围
        int start = i;
        int end = j;

        if(start > end){
            //递归的出口
            return;
        }
        //记录基准数
        int baseNumber = arr[i];
        //利用循环找到要交换的数字
        while (start!=end){
            //利用end，从后往前开始找，找比基准数小的数字
            //int[] arr = {1, 6, 2, 7, 9, 3, 4, 5, 10, 8};
            while (true){
                if (end<=start || arr[end]<baseNumber){
                    break;
                }
                end--;
            }
            System.out.println(end);
            //利用start，从前往后找，找比基准数大的数字
            while (true){
                if (end <= start || arr[start]>baseNumber){
                    break;
                }
                start++;
            }
            //把end和start指向的元素进行交换
            int temp = arr[start];
            arr[start] = arr[end];
            arr[end] = temp;
        }
        //当start和end指向了同一个元素的时候，那么上面的循环就会结束
        //表示已经找到了基准数在数组中应存入的位置
        //基准数归位
        //就是拿着这个范围中的第一个数字，跟start指向的元素进行交换
        int temp = arr[i];
        arr[i] = arr[start];
        arr[start] = temp;

        //确定6左边的范围，重复刚刚所做的事情
        quickSort(arr,i,start - 1);
        //确定6右边的范围，重复刚刚所做的事情
        quickSort(arr,start + 1,j);
    }
}
